package com.frame.library;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewParent;

import androidx.appcompat.widget.VectorEnabledTintResources;
import androidx.core.view.LayoutInflaterCompat;
import androidx.core.view.LayoutInflaterFactory;
import androidx.core.view.ViewCompat;

import com.frame.library.skin.ISkinChangeListener;
import com.frame.library.skin.SkinManager;
import com.frame.library.skin.SkinResource;
import com.frame.library.skin.attr.SkinAttr;
import com.frame.library.skin.attr.SkinView;
import com.frame.library.skin.support.SkinAppCompatViewInflater;
import com.frame.library.skin.support.SkinAttrSupport;
import com.tom.baselibrary.base.BaseActivity;

import java.util.ArrayList;
import java.util.List;

/**
 * Added by Tom on 2024/06/25.
 * 插件换肤功能实现。每个页面都需要换肤。
 */
public abstract class BaseSkinActivity extends BaseActivity implements
        /*LayoutInflater.Factory2*/ LayoutInflaterFactory ,
        ISkinChangeListener {
    private static final String TAG = "BaseSkinActivity";
    private SkinAppCompatViewInflater mSkinAppInflater; // 参考系统实现，兼容6.0新特性

    // 后期添加插件换肤功能。预留层。每次换肤，都遍历集合View，然后修改
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // 添加换肤相关, 在super.onCreate(savedInstanceState) 之前调用。
        LayoutInflater layoutInflater = LayoutInflater.from(this);
        LayoutInflaterCompat.setFactory(layoutInflater, this);
//        LayoutInflaterCompat.setFactory2(layoutInflater, this);
      /*  LayoutInflaterCompat.setFactory(layoutInflater, new LayoutInflaterFactory() {
            @Override
            public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
                // 拦截到View的创建
                // 1. 创建View
                // 2. 拦截属性创建：src，textColor，background 通用属性。
                // 3. 统一交给SkinManager管理。
                return null;
            }
        });*/

        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
        // 拦截到View的创建, 获取view之后要去解析。
        // 1. 创建View, 每个View都会走进来。包括系统的content 的View也会走进来。
        View view = createView(parent, name, context, attrs);
        // Log.e(TAG, "view: " + view); // 每个view创建，都会进入这个回调，打印此日志。
        // 2. 拦截解析 属性：src，textColor，background 通用属性。
        // 一个Activity布局，对应多个这样的SkinView
        if (view != null) {
            List<SkinAttr> skinAttrs = SkinAttrSupport.getSkinAttrs(context, attrs);
            SkinView skinView = new SkinView(view, skinAttrs); // 拼接SkinView：把view和属性加入。
            // 3. 统一交给SkinManager管理。
            managerSkinView(skinView);
            // 4. 判断是否要换肤，如果需要换肤，就使用新皮肤
            SkinManager.getInstance().checkChangeSkin(skinView);
        }
        return view; // 5. 返回创建的 view
    }

    // 统一管理SkinView，交给SkinManager管理。
    private void managerSkinView(SkinView skinView) {
        // 当前Activity中，所有的SkinView。
        List<SkinView> skinViews = SkinManager.getInstance().getSkinViews(this);
        if (skinViews == null) {
            skinViews = new ArrayList<>();
            SkinManager.getInstance().register(skinViews, this);
        }
        skinViews.add(skinView);
    }

    // 参考Google的源码，去创建View。Hook拦截View的创建，在 SkinAppCompatViewInflater 中统一拦截。
    public View createView(View parent, final String name, Context context, AttributeSet attrs) {
        final boolean isPre21 = Build.VERSION.SDK_INT < 21; // API21 以前的版本(5.0 以前的版本)
        if (mSkinAppInflater == null) {
            mSkinAppInflater = new SkinAppCompatViewInflater();
        }
        // We only want the View to inherit its context if we're running pre-v21
        final boolean inheritContext = isPre21 && shouldInheritContext((ViewParent) parent);

        @SuppressLint("RestrictedApi")
        View view = mSkinAppInflater.createView(parent, name, context, attrs, inheritContext,
                isPre21, /* Only read android:theme pre-L (L+ handles this anyway) */
                true, /* Read read app:theme as a fallback at all times for legacy reasons */
                VectorEnabledTintResources.shouldBeUsed() /* Only tint wrap the context if enabled */
        );

        if (view != null) {
//            List<SkinAttr> skinAttrs = SkinSupport.getSkinView(context, attrs);
//            if (skinAttrs.size() != 0) {
//                addSkinManager(view, skinAttrs);
//            }
        }
        return view;
    }

    // 添加到皮肤管理
    private void addSkinManager(View view, List<SkinAttr> skinAttrs) {
        SkinView skinView = new SkinView(view, skinAttrs);
        List<SkinView> skinViews = SkinManager.getInstance().getSkinViews(this);

        if (skinViews == null) {
            skinViews = new ArrayList<>();
//            SkinManager.getInstance().registerSkinView(skinViews, this);
        }
        skinViews.add(skinView);
        // 如果需要换肤
//        if(SkinManager.getInstance().needChangeSkin()){
//            SkinManager.getInstance().changeSkin(skinView);
//        }
    }

    // 从系统源码贴的，google工程师写的基本不会有问题
    private boolean shouldInheritContext(ViewParent parent) {
        if (parent == null) {
            // The initial parent is null so just return false
            return false;
        }
        final View windowDecor = getWindow().getDecorView();
        while (true) {
            if (parent == null) {
                // Bingo. We've hit a view which has a null parent before being terminated from
                // the loop. This is (most probably) because it's the root view in an inflation
                // call, therefore we should inherit. This works as the inflated layout is only
                // added to the hierarchy at the end of the inflate() call.
                return true;
            } else if (parent == windowDecor || !(parent instanceof View)
                    || ViewCompat.isAttachedToWindow((View) parent)) {
                // We have either hit the window's decor view, a parent which isn't a View
                // (i.e. ViewRootImpl), or an attached view, so we know that the original parent
                // is currently added to the view hierarchy. This means that it has not be
                // inflated in the current inflate() call and we should not inherit the context.
                return false;
            }
            parent = parent.getParent();
        }
    }

    @Override
    public void changeSkin(SkinResource skinResource) {
        Log.e(TAG, "changeSkin: in base activity ");
    }

    @Override
    protected void onDestroy() {// 避免内存泄漏
        super.onDestroy();
        // 不再持有引用
        SkinManager.getInstance().unregister(this);
    }


}
